﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.Web;
using Newtonsoft.Json;

using cos_dotnet_sdk;

namespace QCloud.CosApi.Common
{
    enum HttpMethod { Get, Post};
    /// <summary>
    /// 请求调用类
    /// </summary>
    class Request
    {
        static UploadLogger ul = new UploadLogger("ShangChuanLog");
        public string SendRequest(string url, ref Dictionary<string, object> data, HttpMethod requestMethod,
            ref Dictionary<string, string> header, int timeOut, string localPath = null, long offset = -1, int sliceSize = 0)
        {
         
            HttpWebRequest request = null;
            HttpWebResponse response = null;
            try
            {
                //Console.WriteLine("url:" + url);
                ServicePointManager.Expect100Continue = false;
                if (requestMethod == HttpMethod.Get)
                {
                    var paramStr = "";
                    foreach (var key in data.Keys)
                    {
                        paramStr += string.Format("{0}={1}&", key, HttpUtility.UrlEncode(data[key].ToString()));
                    }
                    paramStr = paramStr.TrimEnd('&');
                    url += (url.EndsWith("?") ? "&" : "?") + paramStr;
                }
             ul.Write(url, "requestserver.txt");
                //url = url.Replace("gz.file.myqcloud.com", "14.119.113. 21");
                ul.Write(url, "requestserver.txt");
                Uri uri = new Uri(url);
                request = (HttpWebRequest)HttpWebRequest.Create(uri);
                request.Accept = CosDefaultValue.ACCEPT;
                request.KeepAlive = false;
                request.UserAgent = "User-Agent:Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705";// CosDefaultValue.USER_AGENT_VERSION;
                request.Timeout = timeOut;
                foreach (var key in header.Keys)
                {
                    if(key == "Content-Type")
                    {
                        request.ContentType = header[key];
                    }
                    else
                    {
                        request.Headers.Add(key, header[key]);
                    }
                }
                if (requestMethod == HttpMethod.Post)
                {
                    request.Method = requestMethod.ToString().ToUpper();
                    using (var memStream = new MemoryStream())
                    {
                        if (header.ContainsKey("Content-Type") && header["Content-Type"] == "application/json")
                        {
                            var json = JsonConvert.SerializeObject(data);
                            var jsonByte = Encoding.GetEncoding("utf-8").GetBytes(json.ToString());
                            memStream.Write(jsonByte, 0, jsonByte.Length);
                        }
                        else
                        {
                            var boundary = "---------------" + DateTime.Now.Ticks.ToString("x");
                            var beginBoundary = Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
                            var endBoundary = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
                            request.ContentType = "multipart/form-data; boundary=" + boundary;

                            var strBuf = new StringBuilder();
                            foreach (var key in data.Keys)
                            {
                                strBuf.Append("\r\n--" + boundary + "\r\n");
                                strBuf.Append("Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n");
                                strBuf.Append(data[key].ToString());
                            }
                            var paramsByte = Encoding.GetEncoding("utf-8").GetBytes(strBuf.ToString());
                            memStream.Write(paramsByte, 0, paramsByte.Length);

                            if (localPath != null)
                            {
                                memStream.Write(beginBoundary, 0, beginBoundary.Length);
                                var fileInfo = new FileInfo(localPath);
                                using (var fileStream = new FileStream(localPath, FileMode.Open, FileAccess.Read))
                                {
                                    const string filePartHeader =
                                        "Content-Disposition: form-data; name=\"fileContent\"; filename=\"{0}\"\r\n" +
                                        "Content-Type: application/octet-stream\r\n\r\n";
                                    var headerText = string.Format(filePartHeader, fileInfo.Name);
                                    var headerbytes = Encoding.UTF8.GetBytes(headerText);
                                    memStream.Write(headerbytes, 0, headerbytes.Length);

                                    if (offset == -1)
                                    {
                                        var buffer = new byte[1024];
                                        int bytesRead;
                                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
                                        {
                                            memStream.Write(buffer, 0, bytesRead);
                                        }
                                    }
                                    else
                                    {
                                        var buffer = new byte[sliceSize];
                                        int bytesRead;
                                        fileStream.Seek(offset, SeekOrigin.Begin);
                                        bytesRead = fileStream.Read(buffer, 0, buffer.Length);
                                        memStream.Write(buffer, 0, bytesRead);
                                    }
                                }
                            }
                            memStream.Write(endBoundary, 0, endBoundary.Length);
                        }
                        request.ContentLength = memStream.Length;
 						memStream.Position = 0;
                        var tempBuffer = new byte[memStream.Length];
                        memStream.Read(tempBuffer, 0, tempBuffer.Length);
                        using (var requestStream = request.GetRequestStream())
                        {
                            requestStream.Write(tempBuffer, 0, tempBuffer.Length);
                        }
                    }

                    //Console.WriteLine(strBuf.ToString());
                }

              ul.Write("调用request.GetResponse()", "requestserver.txt");
                //Console.WriteLine(request.ContentType.ToString());
                response = request.GetResponse() as HttpWebResponse;
         
                if (response == null)
                {
                    return "response 为null";
                }

             ul.Write(response.Server,"requestserver.txt");
             ul.Write(response.StatusDescription, "requestserver.txt");
             ul.Write(response.StatusCode.ToString(), "requestserver.txt");

             ul.Write("调用response.GetResponseStream()", "requestserver.txt");
                using (var s = response.GetResponseStream())
                {
              ul.Write("调用response.GetResponseStream()1#", "requestserver.txt");

                    var reader = new StreamReader(s, Encoding.UTF8);
                    ul.Write("调用response.GetResponseStream()2#", "requestserver.txt");
                    return reader.ReadToEnd();
                }
                
            }
            catch (ArgumentException e)
            {
             ul.Write("ArgumentException", "requestserver.txt");
                return e.Message;
            }
            catch (WebException we)
            {
                //if (we.Status == WebExceptionStatus.ProtocolError)
                //{
                //    using (var s = we.Response.GetResponseStream())
                //    {
                //        var reader = new StreamReader(s, Encoding.UTF8);
                //        return reader.ReadToEnd();
                //    }
                //}
                //else
                //{
                //    throw we;
             ul.Write("WebException ", "requestserver.txt");
                return   we.Message;
                //}
            }
            catch (Exception e)
            {
                //throw e;
             ul.Write("Exception", "requestserver.txt");
                return e.Message;
            }
            finally
            {
                if(request != null)
                {
                    try
                    {
                  ul.Write(" request.Abort()", "requestserver.txt");
                        request.Abort();
                    }
                    catch (Exception ex1)
                    {
                  ul.Write(" request.Abort() ex:" + ex1.Message, "requestserver.txt");
                    }
                }

                if(response != null)
                {
                    try
                    {
                      ul.Write(" response.Close()", "requestserver.txt");
                        response.Close();
                    }
                    catch (Exception ex2)
                    {
                      ul.Write(" response.Close() ex:" + ex2.Message, "requestserver.txt");
                    }
                }
            }
        }
    }
}
